<template>
  <!-- 客服聊天弹窗 -->

  <div class="main">
    <h4 class="top_title">
      <span>{{ t("chat_page_with_user", { user: state.userData.TUsername }) }}</span>

      <div class="forbidden">
        <div class="forbidden_btn" @click="visibleForbidden = true" v-if="
          agentInfo.user_type && agentInfo.user_type == 1 && agentInfo.muteuser == 1
        ">
          {{ t("chat_page_mute") }}
        </div>
        <n-switch v-if="false" v-model:value="active" />
        <iconpark-icon @click="isShow = false" class="clo" icon-id="tanctongyguanb" color="#fff" size="1.2rem"
          style="margin-top: 6px"></iconpark-icon>
      </div>
    </h4>
    <div class="main_body">
      <!-- 左侧设置  v-if="agentInfo.user_type && agentInfo.user_type > 0" -->
      <div class="left_setting" v-if="agentInfo.user_type && agentInfo.user_type > 0">
        <div class="set_item" @click="groupClick('all')">
          <n-badge :value="allUnReadNum" :max="999999" class="set_item" :offset="[-14, 0]">
            <iconpark-icon icon-id="zuocweidy01" :color="state.groupType == 'all' ? '#fff' : '#8D84C5'"
              size="1.8rem"></iconpark-icon>
            <!-- <Imgt :src="`/img/serviceModal/${item.img}`" alt=""> -->
            <!-- 全部对话 -->
            <span :style="{ color: state.groupType == 'all' ? '#fff' : '#8D84C5' }">{{
              t("chat_page_all")
            }}</span>
          </n-badge>
        </div>
        <!-- 分组 -->
        <div class="group_area">
          <div class="set_item" v-for="item in groupList" :key="item.id" @click="groupClick(item)">
            <iconpark-icon icon-id="zuocweidy02" :color="state.groupType.id == item.id ? '#fff' : '#8D84C5'"
              size="1.8rem"></iconpark-icon>
            <span :style="{
              color: state.groupType.id == item.id ? '#fff' : '#8D84C5',
            }">{{ item.name }}</span>
          </div>
        </div>
        <!-- 编辑 -->
        <div class="set_item" @click="groupClick('edit')">
          <iconpark-icon icon-id="zuocweidy03" :color="state.groupType == 'edit' ? '#fff' : '#8D84C5'"
            size="1.8rem"></iconpark-icon>
          <span :style="{ color: state.groupType == 'edit' ? '#fff' : '#8D84C5' }">{{
            t("chat_page_edit")
          }}</span>
        </div>
      </div>
      <!-- 左侧菜单 -->
      <div class="left_menu">
        <div style="padding: 0 10px">
          <n-flex class="tabs">
            <div :class="['tab', { active_tab: tab.id == active_id }]" v-for="tab in tab_list" :key="tab.id"
              @click="tabClick(tab)">
              {{ t(tab.label) }}
            </div>
          </n-flex>
          <!-- <div class="mark">
            {{ active_id == 1 ? t("chat_page_chat_list") : t("chat_page_user_list") }}
          </div> -->
          <n-input v-model:value="state.search" :placeholder="t('chat_page_chat_list')">
            <template #suffix>
              <div class="new_btn" @click="searchuser">
                {{ t("chat_page_new_chat") }}
              </div>
            </template>
          </n-input>
          <!-- <n-input v-model:value="search" placeholder="查找聊天列表" v-if="agentInfo.user_type&&agentInfo.user_type>0" /> -->
          <div class="manage_group" @click.stop="manageClick" v-if="agentInfo.user_type && agentInfo.user_type > 0">
            {{ t("chat_page_group") }}
          </div>
        </div>
        <div class="list_wrap">
          <!-- 聊天列表 -->
          <div class="user_list" v-if="active_id == 1">
            <div :class="['list_item', state.activeId == item.id ? 'item_active' : '']"
              v-for="item in state.groupType == 'all' ? chatitemList : groupChatitemList" :key="item.id"
              @click="selectUser(item)" :style="{
                order:
                  item.deep == '0'
                    ? -1
                    : item.istop && item.istop == 1
                      ? 1
                      : item.unreadnums && item.enableflag != 1
                        ? 2
                        : 6,
              }">
              <div class="item_left">
                <div class="avatar">
                  <n-badge :value="item.unreadnums" :show="item.unreadnums > 0" :max="9999" class="set_item"
                    :offset="[-14, 8]">
                    <Imgt :src="`/img/head_icons/${item.THeadPhoto ? item.THeadPhoto : '1002'
                      }.webp`" alt="" class="img1" />
                  </n-badge>
                  <Imgt :src="`/img/serviceModal/vip${item.vip}.webp`" alt="" class="img2" v-if="item.vip" />
                </div>
                <span>{{ item.TUsername }}</span>
              </div>
              <n-popover trigger="hover" placement="bottom-start" :show-arrow="false" :disabled="item.deep == '0'">
                <template #trigger>
                  <div class="high_proxy" :style="{
                    background: setColor(item),
                  }">
                    <span> {{ t(setLabel(item)) }}</span>
                  </div>
                </template>
                <div class="select_wrap">
                  <div v-for="o in selectList.slice(0, 2)" :key="o.id" @click="itemSet(o, item)">
                    <template v-if="item.todeviceid">
                      <!-- 置顶 -->
                      <span v-if="o.id == 1">{{
                        item.istop == 1 ? t("chat_page_cancelTop") : t("chat_page_top")
                      }}</span>
                      <!-- 屏蔽 -->
                      <span v-else>
                        {{
                          item.enableflag == 1
                            ? t("chat_page_cancel_shield")
                            : t("chat_page_shield")
                        }}</span>
                    </template>
                  </div>
                  <div v-if="
                    agentInfo.user_type &&
                    agentInfo.user_type > 0 &&
                    state.groupType == 'all'
                  ">
                    <n-popover trigger="hover" placement="right" :show-arrow="false">
                      <template #trigger>
                        <div class="high_proxy select_group">
                          {{ t("chat_page_moveG") }}
                        </div>
                      </template>
                      <div class="select_wrap_two">
                        <div v-for="o in groupList" :key="o.id" @click="itemAction(item, o)">
                          <span v-if="item.chatgroupid == o.id">√</span>
                          {{ o.name }}
                        </div>
                      </div>
                    </n-popover>
                  </div>
                  <!-- 从分组移除 -->
                  <div v-if="
                    state.groupType != 'all' &&
                    agentInfo.user_type &&
                    agentInfo.user_type > 0
                  " @click="itemSet({ id: 5 }, item)">
                    <span>{{ t("chat_page_group_remove") }}</span>
                  </div>
                </div>
              </n-popover>

              <Imgt :src="`/img/serviceModal/mute.webp`" alt="" class="mute_img" v-if="item.enableflag == 1" />
            </div>
          </div>
          <!-- 好友列表 -->
          <div v-else>
            <div v-for="item in friendList" :key="item.title">
              <div style="margin: 16px 0px 5px 10px">{{ item.title }}</div>
              <div :class="['list_item', state.activeId == i.id ? 'item_active' : '']" v-for="i in item.list"
                :key="i.id" @click="selectUser(i)">
                <div class="item_left">
                  <div class="avatar">
                    <n-badge :show="false" :max="9999" class="set_item" :offset="[-14, 8]">
                      <Imgt :src="`/img/head_icons/${i.THeadPhoto ? i.THeadPhoto : '1002'
                        }.webp`" alt="" class="img1" />
                    </n-badge>
                    <Imgt :src="`/img/serviceModal/vip${i.vip}.webp`" alt="" class="img2" v-if="i.vip" />
                  </div>
                  <span>{{ i.TUsername }}</span>
                </div>

                <div class="high_proxy" :style="{
                  background: setColor(i),
                }">
                  {{ t(setLabel(i)) }}
                </div>
              </div>
            </div>
          </div>
        </div>
      </div>
      <!-- 右侧聊天区域 -->
      <div class="right_content">
        <chatArea :chatList="state.chatMessagesList" :userData="state.userData" :deepObj="deepObj" :setColor="setColor">
        </chatArea>
        <!-- 快捷语选择 -->
        <div class="setting_wrap">
          <div class="short_wrap">
            <n-carousel :slides-per-view="5" :space-between="10" :loop="false" draggable :show-dots="false">
              <div v-for="item in quickPhrasesCateList" :key="item.id">
                <n-popover trigger="hover" placement="top" :show-arrow="false">
                  <template #trigger>
                    <div class="short_wrap_item">
                      <span>{{ item.title }}</span>
                    </div>
                  </template>
                  <div class="short_wrap_list">
                    <span class="short_wrap_title" v-for="op in quickPhrasesList.filter(
                      (ite: any) => ite.qhcid === item.id,
                    )" @click="chooseQuick(op)" :key="op" :style="{
                        order: op.istop == 1 ? 1 : 6,
                      }">{{ op.content }}</span>
                  </div>
                </n-popover>
              </div>
            </n-carousel>
          </div>
          <div class="setting" @click="showSetting" v-if="agentInfo.user_type && agentInfo.user_type > 0">
            {{ t("chat_page_shortcut_set") }}
          </div>
        </div>
        <div class="send_message">
          <!-- <picker set="emojione" /> -->
          <div class="input_content">
            <div id="message-input" ref="msgRef" v-html="initMessage(testMsg)" @paste="optimizePasteEvent"
              contenteditable="true" spellcheck="false" autofocus class="input_wrap"></div>
            <div class="send_icon">
              <iconpark-icon icon-id="ftsx04" size="1.2rem" class="pointer" @click="sendMoney" v-if="
                agentInfo.user_type &&
                agentInfo.user_type == 1 &&
                agentInfo.moneyauth == 1 &&
                false
              " />
              <n-upload @before-upload="beforeUpload" accept=".jpg,.jpeg,.png,.gif" :show-file-list="false">
                <iconpark-icon icon-id="kefuicontlb01" size="1.2rem" class="pointer" />
              </n-upload>
              <n-upload @before-upload="beforeUpload" accept=".mp4,.avi,.mov,.wmv" :show-file-list="false">
                <iconpark-icon icon-id="kefuicontlb02" size="1.2rem" class="pointer" />
              </n-upload>
              <n-popover trigger="hover" :show-arrow="false" placement="top-end">
                <template #trigger>
                  <iconpark-icon icon-id="kefuicontlb03" size="1.2rem" class="pointer" />
                </template>
                <div class="emoji">
                  <EmojiPicker :native="true" @select="onSelectEmoji" />
                </div>
              </n-popover>
            </div>
          </div>
          <div class="send_btn" @click="sendMsg" @keyup.enter="sendMsg">
            {{ t("home_page_send") }}
          </div>
        </div>
      </div>
    </div>
    <!-- 快捷语设置 -->
    <shortcutSettings v-model:visible="visibleSetting" @showCateSetting="showCateSetting"
      @addModifyQuick="addModifyQuick" :quickPhrasesCateList="quickPhrasesCateList"
      :quickPhrasesList="quickPhrasesList" />
    <!-- 快捷语--分类设置 -->
    <categoryList v-model:visible="visibleCateSetting" @addModifyCateQuick="addModifyCateQuick"
      :quickPhrasesCateList="quickPhrasesCateList" />

    <manageGroup ref="groupRef" v-model:visible="visibleGroup" :deepObj="deepObj" :stateData="state"
      :itemList="chatitemList" :agentInfo="agentInfo" />
    <!-- 转账弹窗 -->
    <sendMoneyModal v-model:visible="visibleTransfor" />
    <!-- 禁言弹窗 -->
    <forbiddenSpeech v-model:visible="visibleForbidden" :stateData="state" />
  </div>
</template>

<script setup lang="ts">
import { computed, ref, onMounted, reactive, onUnmounted } from "vue";
import EmojiPicker from "vue3-emoji-picker";
import IWebsocket from "./chatWS";
import "vue3-emoji-picker/css";
import protobuf from "protobufjs";
import chatArea from "./components/chatArea.vue";
import shortcutSettings from "./components/shortcutSettings.vue";
import categoryList from "./components/categoryList.vue";
import manageGroup from "./components/manageGroup.vue";
import sendMoneyModal from "./components/sendMoneyModal.vue";
import forbiddenSpeech from "./components/forbiddenSpeech.vue";
import usechatHooks from "./useHooks";
import { Message } from "@/utils/discreteApi.ts";
import pinia from "@/store/index";
import { storeToRefs } from "pinia";
import { User } from "@/store/user";
import Imgt from "@/components/Imgt.vue";
import { useRoute } from "vue-router";
import { getMinuteDifference } from "@/utils/dateTime";
import { Page } from "@/store/page";
import { Buffer } from "buffer";
// import { Local } from "@/utils/storage";
interface tabType {
  label: string;
  id: number;
}
import { useI18n } from "vue-i18n";

const route = useRoute();
const userInfo = User(pinia);
const page = Page(pinia);
const { roleInfo, agentInfo } = storeToRefs(userInfo);
const { settings } = storeToRefs(page);
const msgRef: any = ref(null);
const groupRef: any = ref(null);
const { t } = useI18n();
const props = defineProps({
  visible: {
    type: Boolean,
    default: false,
  },
});
const deepObj: any = {
  // 上级代理
  "-1": {
    label: "chat_page_up_agent",
    color: "linear-gradient(0deg, #CA2790, #CA2790)",
  },
  // 下级代理
  1: {
    label: "chat_page_down_agent",
    color: "linear-gradient(0deg, #CA2790, #CA2790)",
  },

  2: {
    label: "chat_page_direct_user",
    color:
      "radial-gradient(circle at 50% 0%, #505481, #38406d 49%, #474e82 65%), linear-gradient(to bottom, #fff, #928776)",
  },
  3: {
    label: "chat_page_direct_user",
    color:
      "radial-gradient(circle at 50% 0%, #505481, #38406d 49%, #474e82 65%), linear-gradient(to bottom, #fff, #928776)",
  },

  //官方客服
  0: {
    label: "chat_page_customer",
    color: " linear-gradient(0deg, #F28639, #F28639)",
  },
  5: {
    label: "chat_page_customer",
    color:
      "radial-gradient(circle at 50% 14%, #4c36b3 0%, #3a2786 48%, #3c279a 65%), linear-gradient(to bottom, #fff 0%, #af9eff 102%)",
  },
  //默认
  default: {
    label: "chat_page_direct_user",
    color:
      "radial-gradient(circle at 50% 0%, #489dc3, #3685a9 49%, #489dc3 65%), linear-gradient(to bottom, #fff, #928776)",
  },
};
// const onlyAllowNumber = (value: string) => !value || /^\d+$/.test(value)
const state: any = reactive({
  root: null,
  messagetype: 1, //消息类型
  seqnumber: "",
  chatMessagesList: [], // 聊天消息
  deviceID: roleInfo.value.id, //2654917
  requestid: 5000, //对方ID
  todeviceid: "", //对方设备ID
  firstIn: false,
  messageType: null,
  userData: {},
  activeId: null,
  search: "", // 查询用户
  groupType: "all",
  isEditchat: false,
  autoSendObj: {},
  sendObj: {},
});

// 上传图片视频
const beforeUpload = async (data: any) => {
  await getAgentLevel();
  if ([1].includes(agentInfo.value.mutetype.type_id)) {
    Message.error(t("chat_page_file_error"));
    return;
  }
  const file = data.file.file;
  const fileType = file.type.split("/")[1];
  const type = file.type.includes("image")
    ? "image"
    : file.type.includes("video")
      ? "video"
      : "";

  if (file && file.size > 1024 * 1024 * 2 && type == "image") {
    // 2MB限制
    Message.error(t("chat_page_file_limit1"));
    return;
  }
  if (file && file.size > 1024 * 1024 * 100 && type == "video") {
    // 100MB限制
    Message.error(t("chat_page_file_limit2"));
    return;
  }
  if (type == "image" && !["png", "jpg", "gif", "jpeg"].includes(fileType)) {
    Message.error(t("chat_page_file_error"));
    return;
  }
  const formData = new FormData();
  formData.append(type, file);
  formData.append("device_id", state.deviceID);
  fetch(`http://18.167.175.195:8031/api/upload/${type == "image" ? "img" : "video"}`, {
    method: "POST",
    body: formData,
  })
    .then((response) => response.json())
    .then((response) => {
      if (response.code == 200 || response.status == "success") {
        const urlImg = response.data.path;
        msgRef.value.innerHTML = urlImg;
        state.messagetype = type == "image" ? 3 : 4;
        sendMsg();
      }
    });
};
// 禁止复制图片
const optimizePasteEvent = (e: any) => {
  setTimeout(() => {
    if (e.target.innerHTML.includes("<img")) {
      testMsg.value = msgRef.value.innerHTML = "";
    }
  }, 200);
};

const setLabel = (val: any) => {
  if (agentInfo.value.user_type == 1) {
    const obj: any = {
      0: "chat_page_customer_user",
      5: "chat_page_agent_user",
    };
    return obj[val.agentlevel] || "chat_page_agent_gamer";
  } else {
    return deepObj[val.deep] ? deepObj[val.deep].label : "chat_page_direct_user";
  }
};

const setColor = (item: any) => {
  let color;
  if (item.deep >= 0) {
    color = deepObj[item.deep].color;
  } else if (item.agentlevel == 0 || item.agentlevel == 5) {
    color = deepObj[item.agentlevel].color;
  } else {
    color = deepObj["default"].color;
  }
  return color;
};

const chatObj: any = {};

// 选择用户聊天
const selectUser = (item: any) => {
  const keys = Object.keys(chatObj);

  if (!msgRef.value.innerHTML && state.userData && state.userData.id) {
    chatObj[state.userData.id] = "";
  }
  if (state.userData && state.userData.id) {
    // 已保存草稿的直接读取值
    if (keys.includes(String(item.id))) {
      testMsg.value = chatObj[item.id];
      msgRef.value.innerHTML = chatObj[state.userData.id];
    } else {
      //没保存草稿
      if (msgRef.value.innerHTML) {
        chatObj[state.userData.id] = msgRef.value.innerHTML;
      }
      msgRef.value.innerHTML = testMsg.value = "";
    }
  }
  item.unreadnums = 0;
  state.chatMessagesList = [];
  state.userData = JSON.parse(JSON.stringify(item));
  state.activeId = item.id;
  state.todeviceid = item.Tdeviceid;

  // 获取聊天记录
  synchistorymsg();
  allRead();
  state.userData.unreadnums = 0; // 清掉未读消息
};

const {
  getChatlist,
  getChatMsg13,
  getDateFromat,
  synchistorymsg,
  chatitemList,
  getChatMsg24,
  getChatMsg12,
  initMessage,
  getListGroup,
  encodeParams,
  getShortcutCatelist,
  getShortcutCateMsg,
  sendShortcutCateList,
  getShortcutlist,
  getShortcutMsg,
  sendShortcutList,
  quickPhrasesCateList,
  quickPhrasesList,
  decodeContent,
  itemSet,
  groupList,
  editchat,
  searchuser,
  getChatMsg15,
  groupChatitemList,
  allRead,
  friendList,
  keywordList,
  getkeywordList,
  keywordArr,
}: any = usechatHooks(state, selectUser);

const emit = defineEmits(["update:visible"]);
const active_id = ref(1);
const testMsg = ref("");

const active = ref(true); // 禁言

const tab_list = [
  { label: "chat_page_chat", id: 1 }, // 聊天列表
  { label: "chat_page_user", id: 2 }, // 用户列表
];

// tab 标签点击
const tabClick = (tab: tabType) => {
  active_id.value = tab.id;
};

const selectList = [
  { name: "chat_page_top", id: 1 }, // 置顶
  // { name: '未读', id: 2 },
  { name: "chat_page_shield", id: 3 }, // 屏蔽
  // { name: '取消屏蔽', id: 6 },// 取消屏蔽
  { name: "chat_page_moveG", id: 4 }, // 移动好友到
];
// 添加表情

function onSelectEmoji(emoji: any) {
  testMsg.value = msgRef.value.innerHTML;
  let img = `/:${emoji.r}:/`;
  testMsg.value = testMsg.value + img;
  msgRef.value.innerHTML = testMsg.value;
}

const visibleTransfor = ref(false);
const visibleSetting = ref(false); // 快捷语设置
const visibleCateSetting = ref(false); // 快捷语分类设置
const visibleGroup = ref(false); // 管理分组弹窗
const visibleForbidden = ref(false); // 禁言弹窗

// 转账
const sendMoney = () => {
  visibleTransfor.value = true;
};
// 所有未读消息数量
const allUnReadNum = computed(() => {
  let total = 0;
  chatitemList.value.forEach((item: any) => {
    if (item.unreadnums && item.unreadnums > 0) {
      total = total + item.unreadnums;
    }
  });
  return total;
});

const isShow = computed({
  get: function () {
    return props.visible;
  },
  set: function (value) {
    emit("update:visible", value);
  },
});

// 打开管理分组，获取分组列表
const manageClick = () => {
  visibleGroup.value = true;
  getListGroup();
};

// 打开快捷语设置
const showSetting = () => {
  visibleSetting.value = true;
};
// 打开快捷语分类设置
const showCateSetting = () => {
  visibleCateSetting.value = true;
};

// 分组点击
const groupClick = (item: any) => {
  if (item == "edit") {
    manageClick();
  } else if (item == "all") {
    active_id.value = 1;
    chatitemList.value = [];
    state.groupType = item;
    getChatlist();
  } else {
    active_id.value = 1;
    state.groupType = item;
    groupChatitemList.value = chatitemList.value.filter(
      (o: any) => o.chatgroupid == item.id
    );
  }
};

// 发送消息
const sendMsg = (todeviceid: any = "") => {
  if (!state.todeviceid) {
    return;
  }
  testMsg.value = msgRef.value.innerHTML;
  if (testMsg.value != "") {
    const type = 6; // 给用户发消息
    state.requestid++;
    const requestid = state.requestid;

    const msginput = {
      // data:new TextEncoder().encode(this.jsmessage),
      data: testMsg.value,
    };
    // 是否有敏感词判断 对客服需要
    if (state.messagetype == 1 && keywordArr.value.length && state.userData.deep == "0") {
      keywordArr.value.forEach((item: any) => {
        if (testMsg.value.includes(item)) {
          testMsg.value = testMsg.value?.replaceAll(item, "*".repeat(item.length));
        }
      });
    }
    //编码消息内容
    let MessageTextContentItem = state.root.lookupType("MessageTextContent");
    const errMsg1 = MessageTextContentItem.verify(msginput);
    if (errMsg1) throw new Error(errMsg1);
    const msginputdata = MessageTextContentItem.encode(
      MessageTextContentItem.create(msginput)
    ).finish();
    var datatime = getDateFromat();
    const msgcontent = {
      fromdeviceid: state.deviceID,
      todeviceid: typeof todeviceid == "number" ? todeviceid : state.todeviceid,
      sendtime: datatime,
      mtype: state.messagetype, //文字类型消息
      data: msginputdata,
    };
    // 保存回复用户时间
    state.sendObj[state.todeviceid] = new Date(datatime).getTime();
    //编码消息体
    let MessageInputeItem = state.root.lookupType("MessageInpute");
    const errMsg2 = MessageInputeItem.verify(msgcontent);
    if (errMsg2) throw new Error(errMsg2);
    const msgcontentdata = MessageInputeItem.encode(
      MessageInputeItem.create(msgcontent)
    ).finish();
    // { text: '文字', value: 1 },
    // 	{ text: '表情', value: 2 },
    // 	{ text: '图片', value: 3 },
    // 	{ text: '视频', value: 4 },
    // 	{ text: '转账', value: 5 },
    // 	{ text: 'json', value: 6 },
    // 	{ text: '混合', value: 7 },
    const params = {
      type: type,
      requestid: requestid,
      data: msgcontentdata,
    };
    const encodedRequest = encodeParams(params, "Input");
    let InputItem = state.root.lookupType("Input");
    const buffer = Buffer.from(encodedRequest);
    const decodedMessage = InputItem.decode(buffer);
    const buffer1 = Buffer.from(decodedMessage.data);
    const decodedMessage1 = MessageInputeItem.decode(buffer1);
    const decoder = new TextDecoder("utf-8");
    const decodedString2 = decoder.decode(decodedMessage1.data);
    console.log("decodedMessage1.data :", decodedString2);
    console.log("decodedMessage1.data :", msgcontent);
    // this.sendmessages.push(this.deviceid + ":" + this.jsmessage + "(" + datatime + ")类型:" + msgcontent.mtype)
    IWebsocket.sendMessageHandler(encodedRequest);
  } else {
    Message.error("请输入");
  }
};

const onOpen = async () => {
  if (route.name == "customer") {
    state.deviceID = (localStorage.getItem("device_id") || state.deviceID) * 1;
    const agent_infodata: any = localStorage.getItem("agent_infodata") || {};
    if (agent_infodata) {
      const data = JSON.parse(agent_infodata);
      agentInfo.value = data;
    }
  }

  const type = 1; // PT_SIGN_IN
  const requestid = 5000;
  const singin = {
    deviceid: state.deviceID, //用户的roleid
    userid: state.deviceID, //用户的roleid
    token: "mmssdfasd1155", // Local.get('user').token,//后期从另外一个项目中获取
  };
  const data = encodeParams(singin, "SignInInput");
  const params = {
    type: type,
    requestid: requestid,
    data: data,
  };
  const encodedRequest = encodeParams(params, "Input");
  IWebsocket.sendMessageHandler(encodedRequest);
};
const getChatMsgPublic = (data: any, type?: any) => {
  const decodeobj2 = decodeContent(data.content, "MessageOutpute");
  let obj: any = {
    1: "MessageTextContent", //文字消息
    2: "MessageMoContent", //表情消息
    3: "MessagePicContent", //图片
    4: "MessageVideoContent", //视频
    5: "MessageMoneyContent", //转账
  };
  const decodeobj3 = decodeContent(decodeobj2.data, obj[decodeobj2.mtype]);
  // console.log("onMessage/MessageTextContent output3 ", decodeobj3)
  if (data.cstatus == 1 || data.msgtype == 1) {
    if (!data.cstatus) {
      // 是否有敏感词判断 对客服需要
      if (keywordArr.value.length && state.userData.deep == "0") {
        keywordArr.value.forEach((item: any) => {
          if (decodeobj3.data.includes(item)) {
            decodeobj3.data = decodeobj3.data.replace(item, "*".repeat(item.length));
          }
        });
      }
    }
    const messageObj = {
      cstatus: data.cstatus, // 1; // 通过 显示   等于0或者没有这个字段  就不能显示
      msgtype: data.msgtype,
      date: decodeobj2.sendtime, // 时间
      role: decodeobj2.fromdeviceid == state.deviceID ? 1 : 2, //角色1 我方消息 2 对方消息
      content: decodeobj3.data, //消息
      name: decodeobj2.fromdeviceid == state.deviceID ? "" : state.userData.TUsername,
    };
    if (type == 4 || type == 29) {
      //获取到新消息如果是当前用户直接显示
      if (state.userData.todeviceid == decodeobj2.fromdeviceid) {
        state.chatMessagesList.push(messageObj);
        allRead();
      } else {
        // 不是当前用户则未读消息加1
        const todeviceItem = chatitemList.value.find(
          (item: any) => item.Tdeviceid == decodeobj2.fromdeviceid
        );
        if (todeviceItem) {
          if (todeviceItem.unreadnums && todeviceItem.unreadnums >= 0) {
            todeviceItem.unreadnums++;
          } else {
            todeviceItem.unreadnums = todeviceItem.enableflag != 1 ? 1 : 0;
          }
        }
      }
      autoSend(decodeobj2);
    } else {
      // 聊天记录
      state.chatMessagesList.unshift(messageObj);
    }
  } else {
    // 在审核中
    if (data.msgtype == 3 || data.msgtype == 4) {
      const messageObj = {
        cstatus: data.cstatus, // 1; // 通过 显示   等于0或者没有这个字段  就不能显示
        msgtype: data.msgtype,
        date: decodeobj2.sendtime, // 时间
        role: decodeobj2.fromdeviceid == state.deviceID ? 1 : 2, //角色1 我方消息 2 对方消息
        content: `您发送的${data.msgtype == 3 ? "图片" : "视频"
          }正在审核，请耐心等待，审核通过后显示在前台`, //消息
        name: decodeobj2.fromdeviceid == state.deviceID ? "" : state.userData.TUsername,
      };
      state.chatMessagesList.unshift(messageObj);
    }
  }
};

// 收到对方发来的消息
const getChatMsg4 = (decodeobj1: any, ServiceMessage: string) => {
  const decodeobj00 = decodeContent(decodeobj1.data, ServiceMessage);
  console.log("onMessage/ServiceMessage output1 ", decodeobj00);

  getChatMsgPublic(decodeobj00, decodeobj1.type);
};

// 自动回复

const autoSend = (decodeobj2: any) => {
  // if (state.autoSendObj[decodeobj2.fromdeviceid]) {
  //   state.autoSendObj[decodeobj2.fromdeviceid]

  // }else{
  //   state.autoSendObj[decodeobj2.fromdeviceid] = new Date(decodeobj2.sendtime).getTime()
  // }

  state.autoSendObj[decodeobj2.fromdeviceid] = new Date(decodeobj2.sendtime).getTime();
  startTimer(decodeobj2);
};

// 倒计时开始   3分钟自动回复
const timer = ref();
function startTimer(decodeobj2: any) {
  timer.value = setTimeout(() => {
    if (
      state.sendObj[decodeobj2.fromdeviceid] &&
      state.autoSendObj[decodeobj2.fromdeviceid]
    ) {
      const time1 = state.autoSendObj[decodeobj2.fromdeviceid];
      const time2 = state.sendObj[decodeobj2.fromdeviceid];
      const diffMinus = getMinuteDifference(time1, time2); //几分钟内回复
      if (diffMinus >= 3) {
      }
    } else {
      const msc = quickPhrasesList.value.find((item: any) => item.isautorsp == 1);
      if (msc) {
        testMsg.value = msgRef.value.innerHTML = msc.content;
        sendMsg(decodeobj2.fromdeviceid);
      }
    }
  }, 1000 * 60 * 3);
}

// 清理倒计时
function clear() {
  clearTimeout(timer.value);
  timer.value = null;
}

//  聊天记录
const getChatMsg2 = (decodeobj1: any, SyncResp: string) => {
  const decodeobj00 = decodeContent(decodeobj1.data, SyncResp);
  console.log("onMessage/SyncResp output4 ", decodeobj00);
  if (Object.keys(decodeobj00).length > 0) {
    if (Object.keys(decodeobj00.messages).length > 0) {
      decodeobj00.messages.forEach((item: any) => {
        getChatMsgPublic(item);
      });
    }
  } else {
    state.chatMessagesList = [];
  }
};

// 图片审核通过推送
const getChatMsg29 = (decodeobj1: any, SyncResp: string) => {
  const decodeobj00 = decodeContent(decodeobj1.data, SyncResp);
  getChatMsgPublic(decodeobj00.content, 29);
};

const itemAction = (item: any, o: any) => {
  editchat(item, o);
  state.isEditchat = true;
};
//收到消息
const onMessage: any = async (buffer: any) => {
  const decodeobj1 = decodeContent(buffer, "Output");
  console.log("onMessage/Output output0 ", decodeobj1);
  state.messageType = decodeobj1.type;

  if (decodeobj1.code && decodeobj1.code > 1000) {
    if (decodeobj1.code == "10022") {
      Message.error("删除失败，该分组可能存在下级");
      return;
    }
    if (decodeobj1.code == "10023") {
      Message.error(t(decodeobj1.message));
      var datatime = getDateFromat();
      state.chatMessagesList.push({
        date: datatime,
        role: 1,
        content: testMsg.value,
        name: "",
      });
      return;
    }
    Message.error(t(decodeobj1.message));
    testMsg.value = "";
    msgRef.value.innerHTML = "";
    state.messagetype = 1;
    return;
  }
  if (decodeobj1.type == 6) {
    //给用户发送消息的，确定发送成功还是失败
    // 没返回错误码正常可发送
    if (!decodeobj1.code) {
      var datatime = getDateFromat();
      if (state.messagetype != 1 && agentInfo.value.user_type != 1) {
        testMsg.value = `您发送的${state.messagetype == 3 ? "图片" : "视频"
          }正在审核，请耐心等待，审核通过后显示在前台`;
      }
      state.chatMessagesList.push({
        date: datatime,
        role: 1,
        content: testMsg.value,
        name: "",
      });
    }
    testMsg.value = "";
    msgRef.value.innerHTML = "";
    state.messagetype = 1;
  } else if (decodeobj1.type == 4) {
    // 获取到新消息投递
    getChatMsg4(decodeobj1, "Message");
  }
  //消息同步触发,或者是历史消息 也是使用type等于2下发的
  else if (decodeobj1.type == 2) {
    getChatMsg2(decodeobj1, "SyncResp");
  }
  //消息同步触发,或者是历史消息 也是使用type等于2下发的
  else if (decodeobj1.type == 8) {
    getChatMsg2(decodeobj1, "SyncResp");
  }
  // 保存分组成功
  else if (decodeobj1.type == 13) {
    getChatMsg13(decodeobj1);
  }
  // 移动好友到分组成功
  else if (decodeobj1.type == 14) {
    if (state.isEditchat) {
      // 单独移动到分组
      Message.success(t("operation_success"));
    }
    // Message.success('操作成功')
    getChatlist();
    state.groupType = "all";
    state.isEditchat = false;
  }

  //分组列表保存回执
  else if (decodeobj1.type == 9) {
    Message.success(t("operation_success"));
    groupRef.value.getChatMsg9(decodeobj1);
    getListGroup();
  }
  //分组列表保存回执
  else if (decodeobj1.type == 10) {
    Message.success(t("operation_success"));
    groupRef.value.getChatMsg9(decodeobj1);
  }
  //分组列表删除回执
  else if (decodeobj1.type == 11) {
    getListGroup();
    Message.success(t("operation_success"));
  }
  // 获取分组列表
  else if (decodeobj1.type == 12) {
    getChatMsg12(decodeobj1);
  }
  // 发起新聊天
  else if (decodeobj1.type == 15) {
    getChatMsg15(decodeobj1);
  }
  // 获取客服聊天列表
  else if (decodeobj1.type == 24) {
    getChatMsg24(decodeobj1);
  }
  // 获取关键词列表
  else if (decodeobj1.type == 28) {
    getkeywordList(decodeobj1);
  }
  // 禁言
  else if (decodeobj1.type == 25) {
    Message.success(t("operation_success"));
  }
  // 审核推送
  else if (decodeobj1.type == 29) {
    getChatMsg29(decodeobj1, "MessageItem");
  }

  // 新增，修改，删除快捷语，重新请求列表
  else if ([16, 17, 18].includes(decodeobj1.type)) {
    console.log("----更新快捷语");
    // 删除
    if (decodeobj1.type == 18) {
      Message.success(t("delete_success"));
    }
    getShortcutlist();
    getShortcutCatelist();
  }
  // 快捷语列表
  else if ([19].includes(decodeobj1.type)) {
    console.log("----获取快捷语");
    getShortcutMsg(decodeobj1);
  }
  // 快捷语--分类列表，重新请求列表
  else if ([20, 21, 22].includes(decodeobj1.type)) {
    console.log("----更新快捷语分类");
    // 删除
    if (decodeobj1.type == 22) {
      Message.success(t("delete_success"));
    }

    visibleCateSetting.value = false;
    getShortcutCatelist();
  }
  // 快捷语--分类列表，重新请求列表
  else if ([23].includes(decodeobj1.type)) {
    console.log("----获取快捷语分类");
    getShortcutCateMsg(decodeobj1);
  }
};

// 快捷语选择

const chooseQuick = (data: any) => {
  msgRef.value.innerHTML = data.content;
  sendMsg();
};
// 快捷语增删改查
const addModifyQuick = (data: any) => {
  if (!data.mType) {
    return;
  }
  sendShortcutList(data);
};
// 快捷语--分类增删改查
const addModifyCateQuick = (data: any) => {
  if (!data.mType) {
    return;
  }
  sendShortcutCateList(data);
};

//获取用户角色
async function getAgentLevel() {
  state.deviceID = (localStorage.getItem("device_id") || state.deviceID) * 1;
  if (settings.value.customer_server) {
    // 获取角色
    fetch(settings.value.customer_server + `/api/user/info?device_id=${state.deviceID}`)
      .then((response) => {
        return response.json(); // 将响应解析为 JSON
      })
      .then(async (res) => {
        await User(pinia).setAgentInfo(res?.data);
      });
  }
}

onMounted(async () => {
  await getAgentLevel();
  IWebsocket.conectWebsocket(settings.value.chat_url);
  state.root = await protobuf.load("/connect.ext.proto");
  onOpen();
  IWebsocket.resgisterHandler(onMessage);
  getChatlist();

  getShortcutCatelist();
  getShortcutlist();
  getListGroup();
  keywordList();
  // synchistorymsg()
});

onUnmounted(() => {
  clear();
  IWebsocket.close();
});
</script>
<style lang="less" scoped>
@timestamp: `new Date() .getTime() `;

.main {
  // width: 100%;
  border-radius: 14px;
  border: solid 1.4px #322c59;
  overflow: hidden;
  // background-color: #231353;

  .top_title {
    margin: 0;
    width: 100%;
    position: relative;
    height: 50px;
    line-height: 50px;
    font-size: 16px;
    color: #fff;
    // border-radius: 14px;
    border-top-left-radius: 14px;
    border-top-right-radius: 14px;
    text-align: center;

    box-shadow: 0 4px 4px 0 rgba(0, 0, 0, 0.25);
    background-color: #14173a;
    border-bottom: 1px solid #26294c;

    >.forbidden {
      position: absolute;
      top: 0px;
      right: 15px;
      cursor: pointer;
      display: flex;
      align-items: center;
      gap: 10px;

      .forbidden_btn {
        width: 100px;
        background: url("/img/serviceModal/speech_btn.webp?t=@{timestamp}") no-repeat;
        background-size: 100% 112%;
        color: #fff;
      }
    }

    &:deep(.n-switch--active .n-switch__rail) {
      background-color: #0cc51e;
    }
  }

  .main_body {
    height: 686px;
    display: flex;

    .left_menu {
      padding: 16px 0px;
      height: 100%;
      width: 280px;
      background-color: #171b44;
      box-sizing: border-box;

      &:deep(.n-input__placeholder) {
        // text-align: center;
      }

      .mark {
        margin-bottom: 18px;
        width: 260px;
        height: 36px;
        background-color: #372771;
        border-radius: 10px;
        border: 1px solid #5a47b2;
        display: flex;
        justify-content: center;
        align-items: center;
        color: #8d84c5;

        &:deep(.n-input) {
          .n-input__suffix {
            color: #ca2929;
          }
        }
      }
    }

    .left_setting {
      width: 72px;
      background-color: #1b1f4b;

      box-sizing: border-box;
      display: flex;
      flex-direction: column;
      align-items: center;
      border-right: 3px solid #1d0e4a;

      .set_item {
        margin-top: 24px;
        display: flex;
        flex-direction: column;
        align-items: center;
        cursor: pointer;
        font-size: 14px;

        span {
          padding: 0 6px;
          text-align: center;
          display: inline-block;
          overflow: hidden;
          word-break: break-all;
          text-overflow: ellipsis;
          display: -webkit-box;
          -webkit-line-clamp: 3;
          -webkit-box-orient: vertical;
        }

        img {
          width: 32px;
        }
      }
    }

    .right_content {
      position: relative;
      padding: 0 30px;
      height: 100%;
      width: 920px;
      background-color: #14173a;
    }
  }
}

.tabs {
  margin-bottom: 20px;
  box-sizing: border-box;
  padding: 2px;
  border-radius: 14px;
  background: linear-gradient(0deg, #1d0e4a, #1d0e4a),
    radial-gradient(50% 50% at 50% 50%,
      rgba(126, 126, 126, 0.1) 0%,
      rgba(21, 21, 21, 0.1) 100%),
    linear-gradient(180deg, rgba(0, 0, 0, 0.02) 0%, rgba(0, 0, 0, 0.1) 100%);

  .tab {
    flex: 1;
    height: 46px;
    display: flex;
    align-items: center;
    justify-content: center;
    font-size: 18px;
    color: #8d84c5;
    cursor: pointer;
  }

  .active_tab {
    background: linear-gradient(180deg, #5567ff 0%, #9e1eff 100%);

    color: #fff;
  }
}

.list_wrap {
  height: 420px;
  overflow: auto;
}

.user_list {
  display: flex;
  flex-direction: column;
  // gap: 20px
}

.list_item {
  height: 72px;
  padding: 0 10px;
  cursor: pointer;
  display: flex;
  align-items: center;
  justify-content: space-between;
  position: relative;

  .mute_img {
    width: 18px;
    height: 18px;
    position: absolute;
    right: 8px;
    top: 0;
  }

  .item_left {
    display: flex;
    align-items: center;

    .avatar {
      display: flex;
      flex-direction: column;
      position: relative;

      .img1 {
        height: 50px;
        width: 50px;
        margin-right: 10px;
      }

      .img2 {
        height: 21px;
        position: absolute;
        bottom: -6px;
        // margin-top: -15px;
      }
    }
  }

  .high_proxy {
    cursor: pointer;
    font-size: 12px;
    box-shadow: 0 2px 4px 0 rgba(0, 0, 0, 0.25);
    color: #fff;
    padding: 6px 8px;
    border-radius: 6px;
    background-image: radial-gradient(circle at 50% 0%, #505481, #38406d 49%, #474e82 65%),
      linear-gradient(to bottom, #fff, #928776);
  }
}

.item_active {
  background-color: #282d6a;
}

.send_message {
  //height: 52px;
  display: flex;
  align-items: center;

  &:deep(.n-input) {
    // height: 52px;

    .n-input__input-el {
      // height: 52px;
    }

    .n-input__suffix {
      display: block;
    }
  }

  .send_btn {
    cursor: pointer;
    height: 52px;
    width: 130px;
    margin-left: 16px;
    display: flex;
    justify-content: center;
    align-items: center;
    background: linear-gradient(180deg, #5567ff 0%, #9e1eff 100%);
    border-radius: 8px;
    color: #fff;
  }

  .send_icon {
    margin-top: 10px;
    display: flex;
    gap: 12px;

    img {
      height: 24px;
      width: 24px;
      cursor: pointer;
    }
  }

  &:deep(.n-upload) {
    display: flex;
    align-items: center;

    .n-upload-trigger {
      display: flex;
      align-items: center;
    }
  }
}

.emoji {
  &:deep(.v3-emoji-picker) {
    width: 350px;
    height: 350px;
  }
}

.manage_group {
  display: flex;
  justify-content: flex-end;
  color: #c0c2db;
  margin-top: 12px;
  cursor: pointer;
}

.pointer {
  cursor: pointer;
}

.select_wrap,
.select_wrap_two {
  width: 150px;

  div {
    border-bottom: solid 1px rgba(255, 255, 255, 0.1);
    // height: 36px;
    // line-height: 36px;
    cursor: pointer;
    color: #8e82c2;
    padding-left: 19px;
    overflow: hidden;
    text-overflow: ellipsis;
    display: -webkit-box;
    -webkit-line-clamp: 3;
    -webkit-box-orient: vertical;
    margin-bottom: 10px;

    &:last-child {
      padding-left: 0px;
    }

    &:hover {
      background-color: #1154ff;
      color: #ffffff;
    }

    &:last-child {
      border: unset;
    }
  }
}

.select_wrap_two {
  div {
    padding-left: 19px !important;
  }
}

.setting_wrap {
  display: flex;
  justify-content: space-between;

  .setting {
    cursor: pointer;
    margin-top: 6px;
    padding: 0 20px;
    min-width: 120px;
    height: 40px;
    white-space: nowrap;
    display: flex;
    align-items: center;
    justify-content: center;
    border-radius: 12px;
    box-shadow: inset 0 4px 4px 0 rgba(0, 0, 0, 0.25);
    border: solid 1px #322c59;
    background-color: #1d0e4a;
  }
}

.short_wrap {
  display: flex;
  width: 700px;
  padding-bottom: 6px;
  margin-bottom: 6px;
  margin-top: 12px;

  &::-webkit-scrollbar {
    display: block;
    height: 3px;
  }

  &::-webkit-scrollbar-thumb {
    background: #3c279a;
    border-radius: 8px;
  }

  &:deep(.n-carousel__slide) {
    width: unset !important;
    min-width: 100px !important;
    max-width: 188px !important;
  }

  .short_wrap_item {
    // min-width: 98px;
    // max-width: 158px;
    white-space: nowrap;
    height: 33px;
    display: flex;
    justify-content: center;
    cursor: pointer;
    align-items: center;
    border-radius: 10px;
    background: url("/img/serviceModal/anniu.webp?t=@{timestamp}") no-repeat;
    padding: 0 10px;
    background-size: 100% 100%;
  }
}

.short_wrap_list {
  display: flex;
  flex-direction: column;
  color: #ffffff;
  min-width: 110px;
  // padding: 16px 0px;
  // gap: 10px;

  span {
    cursor: pointer;
    text-align: left;
    display: inline-block;
    padding: 5px 10px;
    border-radius: 4px;
    max-width: 150px;
    overflow: hidden;
    text-overflow: ellipsis;
    display: -webkit-box;
    -webkit-line-clamp: 3;
    -webkit-box-orient: vertical;

    &:hover {
      background-color: #1154ff;
    }
  }
}

:deep(.n-popover) {
  padding: unset !important;

  &:not(.n-popover--raw) {
    overflow: hidden;
    background-image: linear-gradient(to bottom, #2c205c 100%, #261771 -50%),
      linear-gradient(to bottom, #fff 0%, #af9eff 102%);
  }
}

.input_content {
  position: relative;
  width: 100%;
  height: 100%;

  .send_icon {
    position: absolute;
    right: 10px;
    top: 0px;
  }
}

.input_wrap {
  width: 100%;
  height: 80px;
  border-radius: 12px;
  box-shadow: inset 0 4px 4px 0 rgba(0, 0, 0, 0.25);
  border: solid 1px #322c59;
  background-color: #0d0e2e;
  outline: none;
  position: relative;
  padding: 10px;
  padding-right: 135px;
  overflow-y: auto;
}

.new_btn {
  color: #ffffff;
  cursor: pointer;
}

.group_area {
  max-height: 430px;
  overflow-y: auto;
}
</style>
